using System;
using System.Text;
using System.Collections;

namespace PersistenceObject.Framework.Expressions
{
    public class ObjectField : FieldAdapter
    {
        public ObjectField(string name) : base(name)
        {
            this.baseOperator = null;
        }

        public ObjectField(string name, ObjectField basefield) : base(name, basefield)
        {
            this.baseOperator = null;
        }

        public ObjectField As(string name)
        {
            return new ObjectField(string.Format("{0} {1}", this.Name, name), this);
        }

        public ObjectField At(Table table)
        {
            String[] tempArr = this.Name.Split('.');
            if (tempArr.Length > 1)
            {
                this.name = tempArr[1];
            }
            string alias = table.Alias;
            if (string.IsNullOrEmpty(alias))
            {
                alias = table.Name;
            }
            return new ObjectField(string.Format("{0}.{1}", alias, this.Name), this);
        }

        public Expression Between(object lvalue, object rvalue)
        {
            return Expressions.Between(this.Name, lvalue, rvalue);
        }

        public Expression In(IList b)
        {
            return Expressions.In(this.Name, b);
        }

        public Expression In(Table table, Expression exp)
        {
            return this.In(table, this, exp);
        }

        public Expression In(Table table, ObjectField field, Expression exp)
        {
            Expression expression = new InTableFieldExpression(base.Name, table.Name, field.Name);
            expression.Add(new IExpression[] { exp });
            return expression;
        }

        public Expression Like(string value)
        {
            return Expressions.Like(this.Name, value);
        }

        public Expression Match(string value)
        {
            return this.Like(string.Format("%{0}%", value));
        }

        public Expression NotBetween(object lvalue, object rvalue)
        {
            return Expressions.Between(this.Name, lvalue, rvalue, true);
        }

        public Expression NotIn(IList b)
        {
            return Expressions.In(this.Name, b, true);
        }

        public Expression NotIn(Table table, Expression exp)
        {
            return this.NotIn(table, this, exp);
        }

        public Expression NotIn(Table table, ObjectField field, Expression exp)
        {
            InTableFieldExpression expression = new InTableFieldExpression(this.Name, table.Name, field.Name);
            expression.Add(new IExpression[] { exp });
            expression.IsNotIn = true;
            return expression;
        }

        public static ObjectField operator +(ObjectField a, ObjectField b)
        {
            return new ObjectField(string.Concat(new string[] { "(", a.Name, "+", b.Name, ")" }));
        }

        public static ObjectField operator /(ObjectField a, ObjectField b)
        {
            return new ObjectField(string.Concat(new string[] { "(", a.Name, "/", b.Name, ")" }));
        }

        public static Expression operator ==(ObjectField a, object b)
        {
            return Expressions.Equals(a.Name, b);
        }

        public static Expression operator >(ObjectField a, object b)
        {
            return Expressions.GreaterThan(a.Name, b);
        }

        public static Expression operator >=(ObjectField a, object b)
        {
            return Expressions.GreaterThanOrEquals(a.Name, b);
        }

        public static Expression operator !=(ObjectField a, object b)
        {
            return Expressions.NotEquals(a.Name, b);
        }

        public static Expression operator <(ObjectField a, object b)
        {
            return Expressions.LessThan(a.Name, b);
        }

        public static Expression operator <=(ObjectField a, object b)
        {
            return Expressions.LessThanOrEquals(a.Name, b);
        }

        public static ObjectField operator *(ObjectField a, ObjectField b)
        {
            return new ObjectField(string.Concat(new string[] { "(", a.Name, " * ", b.Name, ")" }));
        }

        public static ObjectField operator -(ObjectField a, ObjectField b)
        {
            return new ObjectField(string.Concat(new string[] { "(", a.Name, "-", b.Name, ")" }));
        }

        public FieldValue Set(object value)
        {
            return new FieldValue(this.Name, value);
        }

        private ObjectField baseOperator;
    }
}

